package si.wasu.drawable;

import java.util.HashMap;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.Point;
import android.util.Log;

import javax.vecmath.Point2f;

import si.wasu.drawable.enums.Direction;
import si.wasu.drawable.enums.NumberColor;
import si.wasu.drawable.enums.TrianglePlacement;

public class Triangle {

	private Paint trianglePaint;
	private Path trianglePath;
	private Direction direction;
	private Boolean coupled;

	// x in y levega oglisca
	private Point2f point = new Point2f();

	// sirina (in visina) trikotnika
	public int Twidth;

	// array vseh treh oglisc
	private Point2f[] points = new Point2f[3];

	private boolean active = false;

	private Paint Ap1p2 = new Paint(); // barva od p1 do p2
	private Paint Bp2p3 = new Paint(); // barva od p2 do p3
	private Paint Cp3p1 = new Paint(); // barva od p3 do p1

	private Racun racun12;
	private Racun racun23;
	private Racun racun31;
	
	private TrianglePlacement tp;
	
	private int sideStroke;
	
	private NumberColor numberColor;

	int rposition; // rotational 0-5 (0,60,120,180,240,300)

	HashMap<Integer, Point2f[]> positions = new HashMap<Integer, Point2f[]>();

	public void setColorP1P2(int c) {
		Ap1p2.setColor(c);
	}

	public void setColorP2P3(int c) {
		Bp2p3.setColor(c);
	}

	public void setColorP3P1(int c) {
		Cp3p1.setColor(c);
	}

	public Paint getApaint() {
		return Ap1p2;
	}

	public Paint getBpaint() {
		return Bp2p3;
	}

	public Paint getCpaint() {
		return Cp3p1;
	}

	public void setActive() {
		active = true;
	}

	public void setInActive() {
		active = false;
	}

	public boolean isActive() {
		return active;
	}

	public Paint getTrianglePaint() {
		return trianglePaint;
	}

	public void setTrianglePaint(Paint trianglePaint) {
		this.trianglePaint = trianglePaint;
	}

	public Path getTrianglePath() {
		Point2f[] pts = this.getPoints();
		Point2f p1 = pts[0], p2 = pts[1], p3 = pts[2];
		Path path = new Path();
		path.moveTo(p1.x, p1.y);
		path.lineTo(p2.x, p2.y);
		path.lineTo(p3.x, p3.y);
		this.trianglePath = path;
		return path;
	}

	public void setTrianglePath(Path trianglePath) {
		this.trianglePath = trianglePath;
	}

	public int getTriangleWidth() {
		return Twidth;
	}

	public void setTriangleWidth(int x) {
		Twidth = x;
	}

	public void setPoints(Point2f p1, Point2f p2, Point2f p3) {
		// points[0].x=p1.x;
		// points[0].y=p1.y;
		// points[1].x=p2.x;
		// points[1].y=p2.y;
		// points[2].x=p3.x;
		// points[2].y=p3.y;

		points[0] = p1;
		points[1] = p2;
		points[2] = p3;
	}

	public Point2f[] getPoints() {
		return points;
	}

	public void initSidePaints() {
		Paint paintA = new Paint();
		Paint paintB = new Paint();
		Paint paintC = new Paint();
		
		paintA.setTextSize(15);
		paintB.setTextSize(15);
		paintC.setTextSize(15);

		paintA.setColor(Color.rgb(0, 200, 0));
		paintB.setColor(Color.BLUE);
		paintC.setColor(Color.RED);

		paintA.setStrokeWidth(getSideStroke());
		paintB.setStrokeWidth(getSideStroke());
		paintC.setStrokeWidth(getSideStroke());

		paintA.setAntiAlias(true);
		paintB.setAntiAlias(true);
		paintC.setAntiAlias(true);

		setApaint(paintA);
		setBpaint(paintB);
		setCpaint(paintC);

	}

	public void setApaint(Paint ap1p2) {
		Ap1p2 = ap1p2;
	}

	public void setBpaint(Paint bp2p3) {
		Bp2p3 = bp2p3;
	}

	public void setCpaint(Paint cp3p1) {
		Cp3p1 = cp3p1;
	}

	public Triangle() {
		this(new Point2f(50, 50), 50, new Paint(), TrianglePlacement.INSIDE,new NumberColor("","", ""));
	}

	public Triangle(Point2f p, int triangleWidth, Paint paint, TrianglePlacement tp, NumberColor nc) {
		setPoint(p.x, p.y);
		setTriangleWidth(triangleWidth);
		setTrianglePaint(paint);
		setSideStroke(triangleWidth / 25);
		setTp(tp);
		setNumberColor(nc);
		rposition = getRandomPosition();

		initRacune();
		
//		Log.e("racuns", racun12+" "+racun23+" "+racun31);
		
		setCoupled(false);
		initSidePaints();
		initEquilateralTriangle(p);
	}
	
	private void initRacune() {		
		racun12=new Racun(getNumberColor().getGreen());
		racun23=new Racun(getNumberColor().getBlue());
		racun31=new Racun(getNumberColor().getRed());
	}
	
	private String getRandomPrefix() {
		String[] ops={"+","-","*"};
		int op=(int) (Math.random() * ops.length);
		int c1=(int) (Math.random() * 15);
		int c2=(int) (Math.random() * 15);
		return ops[op]+" "+c1+" "+c2;
	}

	@Deprecated
	private String setRandomRacun() {
		int r=(int)(Math.random() * 10);
		int s=(int)(Math.random() * 10);
		int z=1+(int)(Math.random() * 4);
		String znak="";
		switch (z) {
		case 1: 
			znak="+";
			break;
		case 2: 
			znak="-";
			break;
		case 3: 
			znak="/";
			break;
		case 4: 
			znak="*";
			break;
		}
		return r+" "+znak+" "+s;		
	}
	
	public int getSideStroke() {
		return sideStroke;
	}

	public void setSideStroke(int sideStroke) {
		this.sideStroke = sideStroke;
	}

	public Triangle(Point2f p1, Point2f p2, Point2f p3, Direction d, int width) {
		// konstruktor za trikotnike v gridu - jih ne izrisujemo
		setPoints(p1, p2, p3);
		setDirection(d);
		setTriangleWidth(width);
	}

	public Point2f getPoint() {
		return point;
	}

	public void setPoint(float x, float y) {
		point.x = x;
		point.y = y;
		initEquilateralTriangle(point);
		// setPositions();
	}

	private void setPositions() {
		positions.clear();
		Point2f[] pts = getPoints();
		Point2f p1 = pts[0], p2 = pts[1], p3 = pts[2];
		positions.put(0, new Point2f[] { p1, p2, p3 });
		positions.put(1, new Point2f[] { pts[2], pts[0], pts[1] });
		positions.put(2, new Point2f[] { pts[2], pts[1], pts[0] });
		positions.put(3, new Point2f[] { pts[1], pts[2], pts[0] });
		positions.put(4, new Point2f[] { pts[1], pts[0], pts[2] });
		positions.put(5, new Point2f[] { pts[0], pts[1], pts[2] });
	}

	// p1=center
	// ta metoda samo nastavi tocke p1,p2,p3
	public void initEquilateralTriangle(Point2f center) {
		float visina = Helper.getTriangleHeight(getTriangleWidth());
		// TODO:za zdaj potem en random
		if (direction == null) {
			giveDirection();
		}
		Point2f p1 = null, p2 = null, p3 = null;

		switch (getDirection()) {
		case UP:
			p1 = new Point2f(center.x, center.y - (2f / 3f * visina));
			p2 = new Point2f(p1.x - Twidth / 2f, p1.y + visina);
			p3 = new Point2f(p1.x + Twidth / 2f, p1.y + visina);
			break;
		case DOWN:
			p1 = new Point2f(center.x - Twidth / 2f, center.y - (1f / 3f * visina));
			p2 = new Point2f(center.x, p1.y + visina);
			p3 = new Point2f(p1.x + Twidth, p1.y);
			break;
		}

		switch (rposition) {
		case 0:
		case 1:
			setPoints(p2, p3, p1);
			break;
		case 2:
		case 3:
			setPoints(p3, p1, p2);
			break;
		case 4:
		case 5:
			setPoints(p1, p2, p3);
		}

		// setPoints(p1, p2, p3);
	}

	private void giveDirection() {
		if (direction == null) {
			int r = 1 + (int) (Math.random() * ((3 - 1) + 1));
			switch (1) {
			case 1:
				direction = Direction.UP;
				break;
			case 2:
				direction = Direction.DOWN;
				break;
			case 3:
				direction = Direction.UP;
				break;
			}
		}
	}

	public boolean isPointInTriangle(float x, float y) {
		Point2f p1 = getPoints()[0];
		Point2f p2 = getPoints()[1];
		Point2f p3 = getPoints()[2];
		Point2f p = new Point2f(x, y);
		float alpha = ((p2.y - p3.y) * (p.x - p3.x) + (p3.x - p2.x) * (p.y - p3.y)) / ((p2.y - p3.y) * (p1.x - p3.x) + (p3.x - p2.x) * (p1.y - p3.y));
		float beta = ((p3.y - p1.y) * (p.x - p3.x) + (p1.x - p3.x) * (p.y - p3.y)) / ((p2.y - p3.y) * (p1.x - p3.x) + (p3.x - p2.x) * (p1.y - p3.y));
		float gamma = 1.0f - alpha - beta;
		return alpha > 0 && beta > 0 && gamma > 0;
	}

	public Point2f getTriangleCenter() {
		Point2f p1 = getPoints()[0];
		Point2f p2 = getPoints()[1];
		Point2f p3 = getPoints()[2];
		float x = (p1.x + p2.x + p3.x) / 3f;
		float y = (p1.y + p2.y + p3.y) / 3f;
		return new Point2f(x, y);
	}

	public Direction getDirection() {
		// return direction;
		if (rposition % 2 == 0)
			return Direction.UP;
		else
			return Direction.DOWN;
	}

	public void setDirection(Direction direction) {
		this.direction = direction;
	}

	public int getRposition() {
		return rposition;
	}

	private int getRandomPosition() {
		return (int) (Math.random() * 6);
	}

	public void rotateRight() { // v negativno smer / smer ure
		changeDirection();
		rposition = (6 + (rposition - 1)) % 6; // gre lahko v minus, zato
												// drugace kot pri left rotaciji
		// Point2f[] newpts=positions.get(rposition);
		// setPoints(newpts[0], newpts[1], newpts[2]);
	}

	public void rotateLeft() { // v pozitivno smer / kontra uri
		changeDirection();
		rposition = (rposition + 1) % 6;
		// Point2f[] newpts=positions.get(rposition);
		// setPoints(newpts[0], newpts[1], newpts[2]);
	}

	private void changeDirection() {
		switch (direction) {
		case UP:
			setDirection(Direction.DOWN);
			break;
		case DOWN:
			setDirection(Direction.UP);
			break;
		}
	}

	public Racun getRacun12() {
		return racun12;
	}

	public void setRacun12(Racun racun12) {
		this.racun12 = racun12;
	}

	public Racun getRacun23() {
		return racun23;
	}

	public void setRacun23(Racun racun23) {
		this.racun23 = racun23;
	}

	public Racun getRacun31() {
		return racun31;
	}

	public void setRacun31(Racun racun31) {
		this.racun31 = racun31;
	}

	public TrianglePlacement getTp() {
		return tp;
	}

	public void setTp(TrianglePlacement tp) {
		this.tp = tp;
	}

	public NumberColor getNumberColor() {
		return numberColor;
	}

	public void setNumberColor(NumberColor numberColor) {
		this.numberColor = numberColor;
	}

	public Boolean getCoupled() {
		return coupled;
	}

	public void setCoupled(Boolean coupled) {
		this.coupled = coupled;
	}



}
